package com.my.json;

import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.fasterxml.jackson.databind.ser.std.StdScalarSerializer;
import com.my.core.util.MyJavaTimeModule;
import com.my.json.sensitive.config.SensitiveInfoSerialize;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder;

import java.io.IOException;
import java.text.SimpleDateFormat;
import java.time.ZoneId;
import java.util.Collections;
import java.util.List;
import java.util.Locale;
import java.util.TimeZone;

/**
 * https://www.jianshu.com/p/f3fc3bf6dd2b
 * @author timo 2021/3/3
 */
//@Configuration
//@ConditionalOnClass({ObjectMapper.class})

//@AutoConfigureBefore({JacksonAutoConfiguration.class})
//@EnableConfigurationProperties({BladeJacksonProperties.class})
public class JacksonConfiguration {
    public JacksonConfiguration() {
    }

   // 配置优先级覆盖Jackson 尽管`JacksonConfiguration` 使用了 @Primary 注解，
   // 但Spring MVC会优先使用自定义注册的 HttpMessageConverter ，因此FastJSON转换器会覆盖默认的Jackson转换器
    //FastJSON当前已经注释掉配置，所有生效的还是这个

//    Jackson配置主要影响：
// - 显式使用 ObjectMapper 的代码（如 objectMapper.writeValueAsString() ）
// - 未被FastJSON覆盖的JSON处理场景  注：如果FastJsonConfiguration没有配置HttpMessageConverters，ObjectMapper就全局生效了

    //没有空值转换功能 -- 所以目前使用FastJsonConfiguration进行配置了
    @Primary
    @Bean
    public ObjectMapper objectMapper(Jackson2ObjectMapperBuilder builder) {
        builder.simpleDateFormat("yyyy-MM-dd HH:mm:ss");
        ObjectMapper objectMapper = builder.createXmlMapper(false).build();
        // 注册敏感信息序列化器
//        SimpleModule module = new SimpleModule();
//        module.addSerializer(String.class, new SensitiveInfoSerialize());
//        objectMapper.registerModule(module);
        // 美化输出
        objectMapper.enable(SerializationFeature.INDENT_OUTPUT);
        // 强制JSON 空字符串("")转换为null对象值:
        //https://blog.csdn.net/qq_18515155/article/details/109470630
        objectMapper.enable(DeserializationFeature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT);
        // 允许序列化空的POJO类
        //（否则会抛出异常）
        objectMapper.disable(SerializationFeature.FAIL_ON_EMPTY_BEANS);
//        objectMapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);
        // 把java.util.Date, Calendar输出为数字（时间戳）
        objectMapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
//        objectMapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
        // 在遇到未知属性的时候不抛出异常
        objectMapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
//        objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
        // 在JSON中允许C/C++ 样式的注释(非标准，默认禁用)
        objectMapper.configure(JsonParser.Feature.ALLOW_COMMENTS, true);
        // 允许没有引号的字段名（非标准）
        objectMapper.configure(JsonParser.Feature.ALLOW_UNQUOTED_FIELD_NAMES, true);
        // 允许单引号（非标准）
        objectMapper.configure(JsonParser.Feature.ALLOW_SINGLE_QUOTES, true);
//        String a = "{\"idCard\":\"asa\",jybh:\"\",'userName':\"1212\"}";
//        JSONObject jsonObject = JSON.parseObject(a);
//        InputXml inputXml1 = JSONObject.parseObject(a, InputXml.class);

        // 强制转义非ASCII字符
        // objectMapper.configure(JsonGenerator.Feature.ESCAPE_NON_ASCII, true);
        // 禁用Unicode转义
        objectMapper.configure(JsonGenerator.Feature.ESCAPE_NON_ASCII, false);
        // 将内容包裹为一个JSON属性，属性名由@JsonRootName注解指定
        objectMapper.configure(SerializationFeature.WRAP_ROOT_VALUE, true);

        objectMapper.setLocale(Locale.CHINA);
        objectMapper.setTimeZone(TimeZone.getTimeZone(ZoneId.systemDefault()));
        objectMapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.CHINA));
        objectMapper.configure(JsonParser.Feature.ALLOW_UNQUOTED_CONTROL_CHARS, true);
        objectMapper.configure(JsonParser.Feature.ALLOW_BACKSLASH_ESCAPING_ANY_CHARACTER, true);


        objectMapper.getDeserializationConfig().withoutFeatures(new DeserializationFeature[]{DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES});
        objectMapper.registerModule(MyJavaTimeModule.INSTANCE);
        objectMapper.findAndRegisterModules();
        return objectMapper;
    }

}
